package com.boxin.ims.modules.wechat.busi;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.boxin.framework.base.utils.DateUtils;
import com.boxin.ims.modules.momarketing.common.QRCodeUtils;
import com.boxin.ims.modules.wechat.entity.Lottery;
import com.boxin.ims.modules.wechat.entity.LotteryConfig;
import com.boxin.ims.modules.wechat.entity.LotteryLog;
import com.boxin.ims.modules.wechat.entity.LotteryRecord;
import com.boxin.ims.modules.wechat.entity.Message;
import com.boxin.ims.modules.wechat.entity.NewsReply;
import com.boxin.ims.modules.wechat.entity.WeChat;
import com.boxin.ims.modules.wechat.entity.WechatMember;
import com.boxin.ims.modules.wechat.service.LotteryConfigService;
import com.boxin.ims.modules.wechat.service.LotteryLogService;
import com.boxin.ims.modules.wechat.service.LotteryRecordService;
import com.boxin.ims.modules.wechat.service.LotteryService;
import com.boxin.ims.modules.wechat.service.WechatDaoHelper;
import com.boxin.ims.modules.wechat.service.WechatMemberService;
import com.boxin.ims.modules.wechat.utils.ScoreUtils;
import com.thinkgem.jeesite.common.utils.StringUtils;

/**
 * @author Jakemanse
 * @date 2013-9-23
 * @function <p> 抽奖 处理器 </p>
 */

@Service
public class LotteryProcessor extends BusinessProcessor {
	
	
	
	@Autowired
	private LotteryService lotteryService ;
	
	@Autowired
	private LotteryConfigService lotteryConfigService;
	
	@Autowired
	private LotteryRecordService lotteryRecordService;
	
	
	@Autowired
	private WechatMemberService wechatMemberService;
	
	@Autowired
	private LotteryLogService lotteryLogService;
	
	
	@Autowired
	private WechatDaoHelper wechatDaoHelper;
	
	
	
	
	
	
	private LotteryConfig config;
	
	public LotteryProcessor(){
		super();
	}
	
	
	public LotteryProcessor(WeChat weChat,String openId,HttpServletRequest request,HttpServletResponse response){
		super(weChat, openId, request, response);
	}
	
	public LotteryProcessor(WeChat weChat,String openId) {
		super(weChat,openId);
	}
	
	

	@Override
	public ProcessMessage process() {
		
		String reply ="";
		ProcessMessage message = new ProcessMessage();
		message.setMessageType(Message.MSG_TYPE_TEXT);
		this.config =  lotteryConfigService.getByUserId(user.getId());
		
		if(config == null  || !config.getStartup()){
			reply = "亲,对不起，抽奖活动还没有启动或已经停止，请参与其它的活动吧!";
			writeToUser(reply);
			return message;
		}
		
		WechatMember member =  memberCheckAndReply();
		
		if(member == null) return null;	//非会员不再执行后续动作
		
		//查询我的奖品
		if(this.textMessage.getContent().equals("我的抽奖")){
			queryMineLottery( member );
			return null;
		}
		
		
		//判断今天是否已经参与过抽奖活动
		Date date = new Date();
		date.setHours(0);
		date.setMinutes(0);
		date.setSeconds(0);
		
		
		List<LotteryLog> lotList =  lotteryLogService.findByMemberIdAndDate(user.getId(),member.getId(), date);
		if(config.getRepeats()){	//请允许复重
			if(lotList != null && !lotList.isEmpty() && lotList.size()>=config.getRepeatCount()){
				reply = "亲,对不起,您今天已经参与过"+lotList.size()+"次抽奖活动了已经超过了允许的范围，感谢您的参与，明天继续，本次不扣除您的积分.";
				writeToUser(reply);
				saveLotteryLog(member, null);
				return null;
			}
			
		}else{//不允许重复抽奖
			if(lotList != null && !lotList.isEmpty()){
				reply = "亲,对不起,您今天已经参与过抽奖活动了，感谢您的参与，明天继续，本次不扣除您的积分.";
				writeToUser(reply);
				saveLotteryLog(member, null);
				return null;
			}
			
		}
		
		//看是否有未消费的奖品如果有则不允许再抽取
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("userId", user.getId()+"");
		params.put("memberId", member.getId()+"");
		List myLtyLst = wechatDaoHelper.queryMineLotteryRecordByMember(params);
		if(myLtyLst != null && !myLtyLst.isEmpty()){
			
//			queryMineLottery(member);
//			return null;
			Map<String,Object> rst = (Map<String,Object>)myLtyLst.get(0);
			reply = "亲,对不起,您还有"+myLtyLst.size()+"个奖品未使用，暂时无法参与本次抽奖,请回复【我的抽奖】，查看自己获得奖品，核销使用后再次抽奖,如果您想放弃本奖品请输入【放弃"+rst.get("id")+"】，谢谢！";
			writeToUser(reply);
			saveLotteryLog(member, null);
			return null;
		}
		
		//判断积分是否充足
		if(member.getScore() <  config.getCostScore()){
			reply = "亲,对不起,你当前的积分不足,每次抽奖最低需要"+config.getCostScore()+"积分,谢谢您的参与,试试签到获得积分吧!";
			writeToUser(reply);
			return null;
		}
		//扣除积分
		member.setScore(member.getScore()-config.getCostScore());
		wechatMemberService.save(member);
		ScoreUtils.addWechatMemberCostScore(member, config.getCostScore(), "参与抽奖活动消费积分.");
		
		Lottery mylottery = null;
		List<Lottery> lotteryList = lotteryService.getUserLotteryByUserId(this.weChat.getUser().getId());
		if(lotteryList != null && !lotteryList.isEmpty()){
			
			//抽奖动作
			Lottery lottery = extractLottery(lotteryList);
			mylottery = lottery;
			if(lottery == null){
				reply = "亲,对不起，您没有抽中任何奖品，谢谢您的参与，下次再接再励 !";
			}else{
				
				LotteryRecord record = new LotteryRecord();
				record.setEndTime(DateUtils.getDelayDate(config.getValidDays()));
				record.setLottery(lottery);
				record.setMember(member);
				record.setName(lottery.getName());
				record.setSourceType( LotteryRecord.SOURCE_TYPE_ME);
				record.setStatus(LotteryRecord.STATUS_NORMAL);
				record.setUser(user);
				//中奖记录
				lotteryRecordService.save(record);	
				
				saveLotteryLog(member, lottery);	//中奖日志
				
				//判断是否还有余下的该奖品
				String validDate = DateUtils.formatDate((record.getEndTime()==null)?new Date():record.getEndTime(), "MM月dd日");
				reply = "恭喜您，本次获得了["+lottery.getName()+"]奖品,请务删除此信息,于"+validDate+"之前到店里凭此二维码核销使用,过期作废，如果您想放弃本奖品请输入【放弃"+record.getId()+"】，谢谢！";
				if(lottery.getScore()!=null && lottery.getScore()>0){
					ScoreUtils.addScore(member, lottery.getScore(), "会员中奖");
					
					//加完积分后直接核销
					if(record.getLottery()!=null && Lottery.YES.equals(record.getLottery().getAutoClear())){
						record.setStatus(LotteryRecord.STATUS_CLEAR);
						record.setUpdateTime(new Date());
						record.setRemarks("成功增了"+lottery.getScore()+"个积分并由系统自动核销.");
						lotteryRecordService.save(record);
					}
					
					reply = "恭喜您，本次获得了["+lottery.getName()+"]奖品,您成功增了"+lottery.getScore()+"个积分。";
				}
				String title = "恭喜您中奖了";
				String desc = reply;
				if(StringUtils.isNotEmpty(config.getQrcodeTitle())){
					title = config.getQrcodeTitle();
				}
				if(StringUtils.isNotEmpty(config.getQrcodeDesc())){
					desc = config.getQrcodeDesc();
				}
				
				writeImageToUser(title, desc, record.getQrCode().getId());	//返回二维码给用户
				
				
				return null;
				
			}
			
		}else{
			reply = "亲,对不起，抽奖活动还没有启动，请参与其它的活动吧!";
		}
		
//		LotteryLog lotteryLog = new LotteryLog();
//		lotteryLog.setMember(member);
//		lotteryLog.setName((mylottery==null)?null:mylottery.getName());
//		lotteryLog.setUser(user);
//		lotteryLog.setStatus(LotteryLog.STATUS_NORMAL);
//		lotteryLog.setRemarks("参与抽奖。");
//		lotteryLogService.save(lotteryLog);
		
		
		writeToUser(reply);		//回复用户信息
		
		
		return message;
	}
	
	
	/**
	 * @author Jakemanse
	 * @time 2013-10-18  下午9:32:25
	 * @function <p> 查询我的中奖记录  </p>
	 */
	public void queryMineLottery(WechatMember member ){
		//看是否有未消费的奖品如果有则不允许再抽取
		String reply ="亲,对不起,未找到您的中奖信息,谢谢您的参与!";
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("userId", user.getId()+"");
		params.put("memberId", member.getId()+"");
		List<Map<String, Object> > myLtyLst = wechatDaoHelper.queryMineLotteryRecordByMember(params);
		if(myLtyLst != null && !myLtyLst.isEmpty()){
			
			
			if(myLtyLst.size()==1){	//单条奖品
				Map map =  myLtyLst.get(0);
				Date date = (Date) map.get("end_time");
				String validDate = DateUtils.formatDate(
						(date == null) ? new Date() : date, "MM月dd日");
				
				String title = "您有未使用的奖品【" + map.get("name") + "】";
				String desc = "亲，您有一份未使用的奖品【" + map.get("name") + "】,请于"
						+ validDate + "之前到店里凭此二维码核销使用，过期作废，谢谢！";
				writeSingleLotteryImageToUser(title, desc,
						Long.parseLong(map.get("qrcode_id").toString()));
				
			}else{//多条奖品
				List<NewsReply> newsList = new ArrayList<NewsReply>();
				for (Map<String, Object> row : myLtyLst) {
					NewsReply newsReply = new NewsReply();
					
					Date date = (Date) row.get("end_time");
					String validDate = DateUtils.formatDate(
							(date == null) ? new Date() : date, "MM月dd日");
					
					newsReply.setTitle("您未使用的奖品【"+row.get("name").toString()+"】");
					newsReply.setDescription("您有未使用的奖品【"
							+ row.get("name").toString()+"】请于"+validDate+"之前到店里凭此打开的二维码到服务台核销使用,谢谢!");
					newsReply.setPicUrl(QRCodeUtils.getQRCodePNGURL(Long
							.parseLong(row.get("qrcode_id").toString())));
					newsReply.setUrl(QRCodeUtils.getQRCodePNGURL(Long
							.parseLong(row.get("qrcode_id").toString())));
					newsList.add(newsReply);
				}

				writeQueryLotteryImageToUser(newsList); // 回复
				
			}
			
		}		
	}
	
	
	
	/**
	 * @author Jakemanse
	 * @time 2013-10-18  下午9:32:52
	 * @function <p> 保存抽奖日志 </p>
	 * @param member
	 * @param mylottery
	 */
	public void saveLotteryLog(WechatMember member,Lottery mylottery){
		LotteryLog lotteryLog = new LotteryLog();
		lotteryLog.setMember(member);
		lotteryLog.setName((mylottery==null)?null:mylottery.getName());
		lotteryLog.setUser(user);
		lotteryLog.setStatus(LotteryLog.STATUS_NORMAL);
		lotteryLog.setRemarks("参与抽奖。");
		lotteryLogService.save(lotteryLog);
	}
	
	
	public static String doLottery(List<Lottery> lotteryList,String user){
		
		int rand = new Random().nextInt(10);
		int index = 0;
		String str = "";
		while(true){
			str = "User "+user +" 未中奖，感谢您的参与";
			if(index >= lotteryList.size()) break;
			int rnd = new Random().nextInt(100);
			
			
			Lottery lottery  = lotteryList.get(rnd);
			if(rand <= lottery.getPercent()){
				//System.out.println( "User "+user +" 中的奖品是:"+lottery.getName());
				str = "User "+user +" 中的奖品是:"+lottery.getName();
				break;
			} 
				//System.out.println( "User "+user +" 未中奖，感谢您的参与");
			
			index ++;
		}
		
		//System.out.println( str );
		return str;
	
	}
		
	
	
	/**
	 * @author Jakemanse
	 * @time 2013-9-30  上午10:00:50
	 * @function <p>  </p>
	 * @param args
	 */
	public static void main(String[] args) {
		
		
		Date date = new Date();
		date.setHours(0);
		date.setMinutes(0);
		date.setMinutes(0);
		date.setSeconds(0);
		
		
		System.out.println(date.toGMTString());
		List<Lottery>  lotteryList = new ArrayList<Lottery>();
		Lottery lottery = new Lottery();
		lottery.setName("一等奖品 笔记本电脑一台");
		lottery.setPercent(1);
		lottery.setPeramount(3);
		lottery.setType(Lottery.LOTTERY_TYPE_SPECIFIED);
		lottery.setMobile("1543883322");
		
		lotteryList.add(lottery);
		
		/**
		 * 
		 */
		Lottery lottery2 = new Lottery();
		lottery2.setName("二等奖品 移动硬盘");
		lottery2.setPercent(90);
		lottery2.setPeramount(10);
		lottery2.setType(Lottery.LOTTERY_TYPE_USER);
		lotteryList.add(lottery2);


		Lottery lottery3 = new Lottery();
		lottery3.setName("三等奖品 U盘");
		lottery3.setPercent(80);
		lottery3.setPeramount(30);
		lottery3.setType(Lottery.LOTTERY_TYPE_USER);
		lotteryList.add(lottery3);
		
		
		LotteryProcessor processor = new LotteryProcessor(null,null);
				
		
		for(int i=0;i<100;i++){
//			System.err.println("*******************************"+"user  "+ i+"***********************************");
//			String str = doLottery(lotteryList,"user " + i);
//			System.out.println(str);
			
			Lottery lot = processor.extractLottery(lotteryList);
			if(lot !=null){
				System.out.println("User"+i+"获得到了本次的奖品："+lot.getName());
			}else{
				System.out.println("User"+i+"未中获");
				
			}
		}
		
		
		
		// 1 等奖   比率   5%
		// 2等      比率     30
		// 3等      比率    70
		
		
		
	}
	
	
	
	/**
	* @author zyd
	* @date 2012-10-3
	* @desc:
	* 抽奖奖品
	*/
	public class Reward {
		/**
		 * 奖品编号
		 */
		public int index;
		/**
		 * 奖品名称
		 */
		public String name;
		/**
		 * 中奖概率
		 */
		public int succPercent;

		public Reward(int index, String name, int succPercent) {
			super();
			this.index = index;
			this.name = name;
			this.succPercent = succPercent;
		}

		@Override
		public String toString() {
			return "Reward [index=" + index + ", name=" + name
					+ ", succPercent=" + succPercent + "]";
		}
	}
	
	
	
	public class LotteryHandler {
		public   List<Reward> randomList;

		/**
		 * 获取中奖编码数组
		 * 
		 * @param rlist
		 * @param keyLength
		 * @return
		 */
		public List<Reward> getKeys(List<Reward> rlist, int keyLength) {
			List<Reward> list = new ArrayList<Reward>();
			for (int i = 0; i < keyLength; i++) {
				list.add(getKey(rlist));
			}
			return list;
		}

		/**
		 * 获取中奖编码
		 * 
		 * @param rlist
		 * @return
		 */
		private Reward getKey(List<Reward> rlist) {
			// 随机列表
			List<Reward> randomList = getRandomList(rlist);
			// 根据随机列表得到的概率区段
			List<Integer> percentSteps = getPercentSteps(rlist);
			// 概率区段的最大值
			int maxPercentStep = percentSteps.get(percentSteps.size() - 1);
			// 在概率区段范围内取一个随机数
			int randomStep = new Random().nextInt(maxPercentStep);
			// 中间元素的下标
			int keyIndex = 0;
			int begin = 0;
			int end = 0;
			for (int i = 0; i < percentSteps.size(); i++) {
				if (i == 0) {
					begin = 0;
				} else {
					begin = percentSteps.get(i - 1);
				}
				end = percentSteps.get(i);
				// 判断随机数值是否在当前区段范围内
				if (randomStep > begin && randomStep <= end) {
					keyIndex = i;
					break;
				}
			}
			return randomList.get(keyIndex);
		}

		/**
		 * 获取概率区段[如：10,15,25,30,40,60,75,80,90,95,100]
		 * 
		 * @param rlist
		 * @return
		 */
		private List<Integer> getPercentSteps(List<Reward> rlist) {
			List<Integer> percentSteps = new ArrayList<Integer>();
			int percent = 0;
			for (Reward r : rlist) {
				percent += r.succPercent;
				percentSteps.add(percent);
			}
			return percentSteps;
		}

		/**
		 * 获取随机列表
		 * 
		 * @param rlist
		 * @return
		 */
		private List<Reward> getRandomList(List<Reward> rlist) {
			List<Reward> oldList = new ArrayList<Reward>(rlist);
			List<Reward> newList = new ArrayList<Reward>();
			// 随机排序的老序列中元素的下标
			int randomIndex = 0;
			// 随机排序下标的取值范围
			int randomLength = 0;
			for (int i = 0; i < rlist.size(); i++) {
				// 指向下标范围
				randomLength = oldList.size() - 1;
				// 取值范围元素的个数为多个时，从中随机选取一个元素的下标
				if (randomLength != 0) {
					randomIndex = new Random().nextInt(randomLength);
					// 取值范围元素的个数为一个时，直接返回该元素的下标
				} else {
					randomIndex = 0;
				}
				// 在新的序列当中添加元素，同时删除元素取值范围中的randomIndex下标所对应的元素
				newList.add(oldList.remove(randomIndex));
			}
			return newList;
		}
	}
	
	
	
	
	/**
	 * 获取中奖编码数组
	 * 
	 * @param rlist
	 * @param keyLength
	 * @return
	 */
	public List<Lottery> getKeys(List<Lottery> rlist, int keyLength) {
		List<Lottery> list = new ArrayList<Lottery>();
		for (int i = 0; i < keyLength; i++) {
			list.add(extractLottery(rlist));
		}
		return list;
	}

	/**
	 * 获取中奖编码
	 * 
	 * @param lotteryList
	 * @return
	 */
	private Lottery extractLottery(List<Lottery> lotteryList) {
		// 随机列表
		List<Lottery> randomList = getRandomList(lotteryList);
		// 根据随机列表得到的概率区段
		List<Integer> percentSteps = getPercentSteps(lotteryList);
		// 概率区段的最大值
		int maxPercentStep = percentSteps.get(percentSteps.size() - 1);
		// 在概率区段范围内取一个随机数
		int randomStep = new Random().nextInt(maxPercentStep);
		// 中间元素的下标
		int keyIndex = 0;
		int begin = 0;
		int end = 0;
		for (int i = 0; i < percentSteps.size(); i++) {
			if (i == 0) {
				begin = 0;
			} else {
				begin = percentSteps.get(i - 1);
			}
			end = percentSteps.get(i);
			// 判断随机数值是否在当前区段范围内
			if (randomStep > begin && randomStep <= end) {
				keyIndex = i;
				break;
			}
		}
		
		Lottery lottery = randomList.get(keyIndex);	//已抽到的奖
		
		//抽到后再进行两次机率计算，一个是奖品本身的机率，2是合璧的机率
		
		//
		
		int  lastRand = new Random().nextInt(100);
		if(config!=null && config.getPercent()!=null){
			
			if(lastRand <config.getPercent()){
				int myrand = new Random().nextInt(100);//自身随机机率
				if(lottery !=null && myrand <= lottery.getPercent()){
					
					return lottery;
				}else{
					return null;
				}
				
			}else{
				return null;
			}
		}else{
			
			
			return lottery; 
		}
		
	}

	/**
	 * 获取概率区段[如：10,15,25,30,40,60,75,80,90,95,100]
	 * 
	 * @param rlist
	 * @return
	 */
	private List<Integer> getPercentSteps(List<Lottery> rlist) {
		List<Integer> percentSteps = new ArrayList<Integer>();
		int percent = 0;
		for (Lottery r : rlist) {
			percent += r.getPercent();
			percentSteps.add(percent);
		}
		return percentSteps;
	}

	/**
	 * 获取随机列表
	 * 
	 * @param rlist
	 * @return
	 */
	private List<Lottery> getRandomList(List<Lottery> rlist) {
		List<Lottery> oldList = new ArrayList<Lottery>(rlist);
		List<Lottery> newList = new ArrayList<Lottery>();
		// 随机排序的老序列中元素的下标
		int randomIndex = 0;
		// 随机排序下标的取值范围
		int randomLength = 0;
		for (int i = 0; i < rlist.size(); i++) {
			// 指向下标范围
			randomLength = oldList.size() - 1;
			// 取值范围元素的个数为多个时，从中随机选取一个元素的下标
			if (randomLength != 0) {
				randomIndex = new Random().nextInt(randomLength);
				// 取值范围元素的个数为一个时，直接返回该元素的下标
			} else {
				randomIndex = 0;
			}
			// 在新的序列当中添加元素，同时删除元素取值范围中的randomIndex下标所对应的元素
			newList.add(oldList.remove(randomIndex));
		}
		return newList;
	}


	@Override
	public boolean isNeedBeMember() {
		return true;
	}

}
